<?php

	class Config extends SimpleXMLElement
	{
		public static function load( $filename )
		{
			libxml_use_internal_errors(true);
			
			libxml_clear_errors();
			
			if ( ! ( $xml = simplexml_load_file( $filename, "Config", LIBXML_DTDATTR ) ) )
			{
				$errors = libxml_get_errors();
				$xml    = explode( "\n", @file_get_contents( $filename ) );
				
				foreach( $errors as $error )
					error_log( Config::format_xml_error( $error, $xml ) );
				
				libxml_clear_errors();
				
				return false;
			}
			
			return $xml;
		}
		
		public function get( $node_name )
		{
			return $this->getArray( "/" . $node_name );
		}
		
		public function getArray( $xpath = false )
		{
			if ( $xpath !== false )
				if ( ! $xml = $this->xpath( $xpath ) )
					$xml = $this;
				
			return $this->__toArray( $this );
		}
		
		private function __toArray( $xml = false ) 
		{
			$fils  = 0;
			$tab   = false;
			$array = Array();
			
			foreach( $xml->children() as $key => $value )
			{   
				$child = $this->__toArray( $value );
			   
				// To deal with the attributes
				foreach( $value->attributes() as $ak => $av )
					$child[$ak] = (string)$av;
			   
				// Lets see if the new child is not in the array
				if( $tab == false && in_array( $key, array_keys( $array ) ) )
				{
					// If this element is already in the array we will create an indexed array
					$tmp = $array[ $key ];
					
					$array[ $key ] = Array();
					
					$array[ $key ][] = $tmp;
					$array[ $key ][] = $child;
					
					$tab = true;
				}
				
				else if( $tab == true )
					// Add an element in an existing array
					$array[ $key ][] = $child;
				else
					// Add a simple element
					$array[ $key ] = $child;
					   
				$fils++;       
			  }
		   
		   
			if( $fils == 0 )
				return (string)$xml;
		   
			return $array;
		}
		
		public function getAttributesArray()
		{
			$attributes = Array();
			
			foreach( $this->attributes() as $a => $b )
				$attributes[$a] = (string) $b;
			
			return (array) $attributes;
		}
		
		static function format_xml_error($error, $xml)
		{
			$return = "";
			
			if ( 0 < $error->line && $error->line <= sizeof( $xml ) )
				$return  .= $xml[ $error->line - 1 ] . "\n";
			
			$return .= str_repeat('-', $error->column) . "^\n";
		
			switch ($error->level) {
				case LIBXML_ERR_WARNING:
					$return .= "Warning $error->code: ";
					break;
				 case LIBXML_ERR_ERROR:
					$return .= "Error $error->code: ";
					break;
				case LIBXML_ERR_FATAL:
					$return .= "Fatal Error $error->code: ";
					break;
			}
		
			$return .= trim($error->message) .
					   "\n  Line: $error->line" .
					   "\n  Column: $error->column";
		
			if ($error->file) {
				$return .= "\n  File: $error->file";
			}
		
			return "$return\n\n--------------------------------------------\n\n";
		}
	}

?>